import vtkmodules.all as vtk
import json
import copy
from CloudEngine.core.TEdge import TEdge


class GyLoader:

    def __init__(self, json_str: str) -> None:
        # 自带属性
        self.gy_data = None
        self.face_id_points_map = dict()
        self.vertexes_map = dict()
        self.triangles_map = dict()
        self.triangle_points_map = dict()
        self.face_triangles_points_map = dict()
        self.face_triangles_map = dict()
        # 初始化属性
        self.poly_data = vtk.vtkPolyData()
        self.outLinePolyData = vtk.vtkPolyData()
        self.points = vtk.vtkPoints()
        self.cells = vtk.vtkCellArray()
        self.lines = vtk.vtkCellArray()
        self.point_index_map = set()
        json_obj = json.loads(json_str)
        self.gy_data = {
            "nodes": json.loads(json_obj.get("nodes")),
            "faceIds": json.loads(json_obj.get("faceIds")),
            "triangles": json.loads(json_obj.get("triangles")),
            "faceTriNums": json.loads(json_obj.get("faceTriNums")),
            "edgeIds": json.loads(json_obj.get("edgeIds")),
            "outlines": json.loads(json_obj.get("outlines")),
            "faceEdges": json.loads(json_obj.get("faceEdges")),
            "vertexes": json.loads(json_obj.get("vertexs")),
            "faceEdgesNums": json.loads(json_obj.get("faceEdgesNums")),
            "edgeLineNums": json.loads(json_obj.get("edgeLineNums")),
            "normals": json.loads(json_obj.get("normals")),
            "edgeTypes": json_obj.get("edgeTypes"),
        }
        result = self.parse_cells_from_gy_data()
        self.vertexes_map = result.get("vertexes_map")
        self.triangles_map = result.get("triangles_map")
        self.triangle_points_map = result.get("triangle_points_map")
        self.create_point_data()
        self.create_cell_data()
        self.create_outlines()
        self.poly_data.SetPoints(self.points)
        # 设置法向量
        self.insert_normals()
        self.poly_data.SetPolys(self.cells)
        self.outLinePolyData.SetPoints(self.points)
        self.outLinePolyData.SetLines(self.lines)
        # 设置轮廓边数据
        self.edgeData = TEdge(self.outLinePolyData, self.gy_data.get("edgeIds"),
                              self.gy_data.get("edgeLineNums"),
                              self.gy_data.get("edgeTypes"))

    def parse_cells_from_gy_data(self):
        TMP_triangles: [int] = copy.copy(self.gy_data.get("triangles"))
        TMP_nodes: [int] = copy.copy(self.gy_data.get("nodes"))
        TMP_edgeIds: [int] = copy.copy(self.gy_data.get("edgeIds"))
        TMP_outlines: [int] = copy.copy(self.gy_data.get("outlines"))
        TMP_vertexes: [int] = copy.copy(self.gy_data.get("vertexes"))
        TMP_edgeLineNums: [int] = copy.copy(self.gy_data.get("edgeLineNums"))
        TMP_faceEdgeNums: [int] = copy.copy(self.gy_data.get("faceEdgesNums"))
        TMP_faceEdges: [int] = copy.copy(self.gy_data.get("faceEdges"))
        TMP_faceIds: [int] = copy.copy(self.gy_data.get("faceIds"))
        TMP_faceTriNums: [int] = copy.copy(self.gy_data.get("faceTriNums"))

        # ✅ 处理顶点坐标
        vertexes_map = dict()

        index1 = 0
        while index1 < len(TMP_vertexes):
            vertexes_map[TMP_vertexes[index1 + 1]] = [
                TMP_nodes[3 * TMP_vertexes[index1]],
                TMP_nodes[3 * TMP_vertexes[index1] + 1],
                TMP_nodes[3 * TMP_vertexes[index1] + 2]
            ]
            index1 += 2

        # ✅ 处理每个三角形所包含的点坐标
        triangle_points_map = dict()
        index2 = 0
        while index2 < len(TMP_triangles) / 3:
            triangle_points_map[index2] = \
                [
                    [
                        TMP_nodes[3 * TMP_triangles[index2]],
                        TMP_nodes[3 * TMP_triangles[index2] + 1],
                        TMP_nodes[3 * TMP_triangles[index2] + 2],
                    ],
                    [
                        TMP_nodes[3 * TMP_triangles[index2 + 1]],
                        TMP_nodes[3 * TMP_triangles[index2 + 1] + 1],
                        TMP_nodes[3 * TMP_triangles[index2 + 1] + 2],
                    ],
                    [
                        TMP_nodes[3 * TMP_triangles[index2 + 2]],
                        TMP_nodes[3 * TMP_triangles[index2 + 2] + 1],
                        TMP_nodes[3 * TMP_triangles[index2 + 2] + 2],
                    ],
                ]
            index2 += 1

        # ✅ 处理每个三角形包含的顶点
        triangles_map = dict()
        index3 = 0
        while index3 < len(TMP_triangles) / 3:
            triangles_map[index3] = \
                [
                    TMP_triangles[index3 * 3],
                    TMP_triangles[index3 * 3 + 1],
                    TMP_triangles[index3 * 3 + 2],
                ]
            index3 += 1

        # print("vertexes_map", vertexes_map)
        # print("triangle_points_map", triangle_points_map)
        # print("triangles_map", triangles_map)

        return {
            "vertexes_map": vertexes_map,
            "triangle_points_map": triangle_points_map,
            "triangles_map": triangles_map,
        }

    def create_point_data(self):
        TMP_nodes = copy.copy(self.gy_data.get("nodes"))
        TMP_arr = vtk.vtkFloatArray()
        TMP_arr.SetNumberOfComponents(3)
        index = 0
        while index < len(TMP_nodes) / 3:
            point = (
            TMP_nodes[3 * index], TMP_nodes[3 * index + 1], TMP_nodes[3 * index + 2])
            TMP_arr.InsertNextTuple3(*point)
            index += 1

        self.points.SetData(TMP_arr)

    def create_cell_data(self):
        for key, value in self.triangles_map.items():
            self.cells.InsertNextCell(len(value), copy.copy(value))

    def create_outlines(self):
        # origin code 
        # outlines = copy.copy(self.gy_data.get("outlines"))
        # index = 0
        # while index < len(outlines) / 2:
        #     self.lines.InsertNextCell(2, [
        #         outlines[2 * index],
        #         outlines[2 * index + 1]
        #     ])
        #     index += 1

        outlines = copy.copy(self.gy_data.get("outlines"))
        index = 0
        while index < len(outlines) / 2:
            line = vtk.vtkLine()
            line.GetPointIds().SetId(0, outlines[2 * index])
            line.GetPointIds().SetId(1, outlines[2 * index + 1])
            self.lines.InsertNextCell(line)
            index += 1

    def insert_normals(self):
        normals = vtk.vtkFloatArray()
        normals.SetNumberOfComponents(3)
        normals.SetName("Normals")
        i = 0
        origin = self.gy_data.get("normals")
        while i < len(origin) / 3:
            normals.InsertNextTuple3(origin[3 * i], origin[3 * i + 1],
                                     origin[3 * i + 2])
            i += 1
        self.poly_data.GetPointData().SetNormals(normals)
